home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-09-30 | 58.8 KB | 2,067 lines |
- Newsgroups: comp.sources.misc
- organization: Tektronix Inc., Beaverton, Or.
- subject: v08i089: unzipbsd 2.0
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Reply-To: michaele@vice.ico.tek.com (Michael Enkelis)
-
- Posting-number: Volume 8, Issue 89
- Submitted-by: michaele@vice.ico.tek.com (Michael Enkelis)
- Archive-name: unzipbsd
-
- This should handle ZIP files made with version 1.1
-
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # Makefile
- # unzipbsd.c
- # crc32.c
- # patchlevel.h
- # unzip.doc
- # This archive created: Tue Sep 26 16:26:16 1989
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'Makefile'" '(928 characters)'
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'Makefile'
- X# Makefile for unzipbsd
- X
- X
- X# "make unzip" -- makes unzip in current directory
- X# "make install" -- makes unzip, then moves it into DESTDIR defined below
- X# "make clean" -- deletes object files and executable unzip from current dir
- X# "make shar" -- make a SHell ARchive
- X# "make arc" -- make a DOS archive
- X
- X# Directory where we want to move executable unzip on "make install"
- XDESTDIR=/usr/public
- X
- X# CFLAGS are flags for the C compiler. LDFLAGS are flags for the loader.
- XCFLAGS= -O
- X# This is used for DBX
- X#CFLAGS= -g
- X
- XLDFLAGS= -s
- X
- XCC=cc
- X
- X.c.o:
- X $(CC) -c $(CFLAGS) $*.c
- X
- XSRCS = unzipbsd.c crc32.c patchlevel.h
- XOBJS = unzipbsd.o crc32.o
- X
- Xunzip: $(OBJS)
- X cc $(LDFLAGS) -o unzip $(OBJS)
- X
- Xunzip.o: unzip.c
- X
- Xcrc32.o: crc32.c
- X
- Xinstall: unzip
- X mv unzip $(DESTDIR)/unzip
- X
- Xclean:
- X /bin/rm -f $(OBJS) core unzip
- X
- Xshar:
- X @shar -a Makefile $(SRCS) unzip.doc > unzipbsd.shar
- X
- Xarc:
- X @arc -a unzipbsd.arc Makefile $(SRCS) unzip.doc
- X
- SHAR_EOF
- if test 928 -ne "`wc -c < 'Makefile'`"
- then
- echo shar: error transmitting "'Makefile'" '(should have been 928 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'unzipbsd.c'" '(42309 characters)'
- if test -f 'unzipbsd.c'
- then
- echo shar: will not over-write existing file "'unzipbsd.c'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'unzipbsd.c'
- X
- X/*
- X * Copyright 1989 Samuel H. Smith; All rights reserved
- X *
- X * Do not distribute modified versions without my permission.
- X * Do not remove or alter this notice or any other copyright notice.
- X * If you use this in your own program you must distribute source code.
- X * Do not use any of this in a commercial product.
- X *
- X */
- X
- X/*
- X * UnZip - A simple zipfile extract utility
- X *
- X * To compile:
- X * tcc -B -O -Z -G -mc unzip.c ;turbo C 2.0, compact model
- X *
- X */
- X
- X#include "patchlevel.h"
- X#define VERSION "2.0"
- X
- Xtypedef unsigned char byte; /* code assumes UNSIGNED bytes */
- Xtypedef long longint;
- Xtypedef unsigned word;
- Xtypedef char boolean;
- X
- X#define STRSIZ 256
- X
- X#include <stdio.h>
- X /* this is your standard header for all C compiles */
- X#include <ctype.h>
- X
- X#ifdef MSDOS || M_XENIX
- X#include <stdlib.h>
- X /* this include defines various standard library prototypes */
- X#endif
- X
- X
- X/*
- X * SEE HOST OPERATING SYSTEM SPECIFICS SECTION STARTING NEAR LINE 180
- X *
- X */
- X
- X
- X/* ----------------------------------------------------------- */
- X/*
- X * Zipfile layout declarations
- X *
- X */
- X
- X
- Xchar local_file_header_signature[] = {0x50,0x4b,0x03,0x04};
- X
- X
- Xtypedef struct local_file_header {
- X word version_needed_to_extract;
- X word general_purpose_bit_flag;
- X word compression_method;
- X word last_mod_file_time;
- X word last_mod_file_date;
- X longint crc32;
- X longint compressed_size;
- X longint uncompressed_size;
- X word filename_length;
- X word extra_field_length;
- X} local_file_header;
- X
- X
- Xchar central_file_header_signature[] = {0x50,0x4b,0x01,0x02};
- X
- X
- Xtypedef struct central_directory_file_header {
- X word version_made_by;
- X word version_needed_to_extract;
- X word general_purpose_bit_flag;
- X word compression_method;
- X word last_mod_file_time;
- X word last_mod_file_date;
- X longint crc32;
- X longint compressed_size;
- X longint uncompressed_size;
- X word filename_length;
- X word extra_field_length;
- X word file_comment_length;
- X word disk_number_start;
- X word internal_file_attributes;
- X longint external_file_attributes;
- X longint relative_offset_local_header;
- X} central_directory_file_header;
- X
- X
- Xchar end_central_dir_signature[] = {0x50,0x4b,0x05,0x06};
- X
- X
- Xtypedef struct end_central_dir_record {
- X word number_this_disk;
- X word number_disk_with_start_central_directory;
- X word total_entries_central_dir_on_this_disk;
- X word total_entries_central_dir;
- X longint size_central_directory;
- X longint offset_start_central_directory;
- X word zipfile_comment_length;
- X} end_central_dir_record;
- X
- X
- X
- X/* ----------------------------------------------------------- */
- X/*
- X * input file variables
- X *
- X */
- X
- X#define INBUFSIZ 0x2000
- Xbyte *inbuf; /* input file buffer - any size is legal */
- Xbyte *inptr;
- Xbyte *comment;
- X
- Xint incnt;
- Xunsigned bitbuf;
- Xint bits_left;
- Xboolean zipeof;
- X
- Xint zipfd;
- Xchar zipfn[STRSIZ];
- Xlocal_file_header lrec;
- X
- X
- X/* ----------------------------------------------------------- */
- X/*
- X * output stream variables
- X *
- X */
- X
- X#define OUTBUFSIZ 0x6000
- Xbyte *outbuf; /* buffer for rle look-back */
- Xbyte *outptr;
- X
- Xlongint outpos; /* absolute position in outfile */
- Xint outcnt; /* current position in outbuf */
- X
- Xint outfd;
- Xchar filename[STRSIZ];
- Xchar extra[STRSIZ];
- X
- X#define DLE 144
- X
- X
- X/* ----------------------------------------------------------- */
- X/*
- X * shrink/reduce working storage
- X *
- X */
- X
- Xint factor;
- Xbyte followers[256][64];
- Xbyte Slen[256];
- X
- X#define max_bits 13
- X#define init_bits 9
- X#define hsize 8192
- X#define first_ent 257
- X#define clear 256
- X
- Xtypedef int hsize_array_integer[hsize+1];
- Xtypedef byte hsize_array_byte[hsize+1];
- X
- Xhsize_array_integer prefix_of;
- Xhsize_array_byte suffix_of;
- Xhsize_array_byte stack;
- X
- Xint codesize;
- Xint maxcode;
- Xint free_ent;
- Xint maxcodemax;
- Xint offset;
- Xint sizex;
- X
- X
- X
- X/* ============================================================= */
- X/*
- X * Host operating system details
- X *
- X */
- X
- X#include <string.h>
- X /* this include defines strcpy, strcmp, etc. */
- X
- X#include <time.h>
- X
- X#ifdef MSDOS || M_XENIX
- X#include <io.h>
- X /*
- X * this include file defines
- X * struct ftime ... (* file time/date stamp info *)
- X * int setftime (int handle, struct ftime *ftimep);
- X * #define SEEK_CUR 1 (* lseek() modes *)
- X * #define SEEK_END 2
- X * #define SEEK_SET 0
- X */
- X#else
- X#include <sys/file.h>
- X /*
- X * this include file defines
- X * #define L_SET 0 (* Seek to absolute record *)
- X */
- X#define SEEK_SET L_SET
- X#endif
- X
- X
- X
- X#ifdef MSDOS || M_XENIX
- X#include <fcntl.h>
- X /*
- X * this include file defines
- X * #define O_BINARY 0x8000 (* no cr-lf translation *)
- X * as used in the open() standard function
- X */
- X#ifndef L_SET
- X#define L_SET 1
- X#endif
- X#endif
- X
- X#ifndef O_BINARY
- X#define O_BINARY 0 /* BSD don't have a Open_BINARY mode */
- X#endif
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X /*
- X * this include file defines
- X * #define S_IREAD 0x0100 (* owner may read *)
- X * #define S_IWRITE 0x0080 (* owner may write *)
- X * as used in the creat() standard function
- X */
- X
- Xvoid set_file_time()
- X /*
- X * set the output file date/time stamp according to information from the
- X * zipfile directory record for this file
- X */
- X{
- X /*
- X * set output file date and time - this is optional and can be
- X * deleted
- X */
- X
- X#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
- X#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
- X
- X byte yr, mo, dy; /* parts of a date */
- X byte hh, mm, ss; /* parts of a time */
- X static char month_lengths[] =
- X { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- X int day_of_year, year;
- X struct utimbuf {
- X time_t actime; /* file accessed time */
- X time_t modtime; /* file updated time */
- X } times;
- X
- X yr = (lrec.last_mod_file_date >> 9) & 0x7f; /* dissect the date */
- X mo = (lrec.last_mod_file_date >> 5) & 0x0f;
- X dy = lrec.last_mod_file_date & 0x1f;
- X
- X hh = (lrec.last_mod_file_time >> 11) & 0x1f; /* dissect the time */
- X mm = (lrec.last_mod_file_time >> 5) & 0x3f;
- X ss = (lrec.last_mod_file_time & 0x1f) * 2;
- X yr = (yr + 80) % 100;
- X year = yr + 1900;
- X
- X /*
- X * this is the standard Unix implementation (also fully
- X * compatible with MSC)
- X */
- X
- X close(outfd);
- X if (mo < 1 || mo > 12 || dy < 1 || dy > month_lengths[mo-1]
- X && !(mo == 2 && dy == 29 && leap (year))
- X || hh > 23 || mm > 59 || ss > 59)
- X return;
- X
- X day_of_year = dy - 1;
- X if (mo > 2 && leap(year))
- X ++day_of_year;
- X
- X while (--mo > 0)
- X day_of_year += month_lengths[mo - 1];
- X
- X times.modtime = (86400 * (long)(day_of_year + 365 * (year - 1970)
- X + nleap (year)) + 3600 * (hh-1) + 60 * mm + ss);
- X
- X#ifdef HAVE_TZ
- X tzset();
- X times.modtime += timezone;
- X#endif /* HAVE_TZ */
- X times.actime = times.modtime;
- X utime(filename, ×);
- X}
- X
- X/*
- X * Some defines to use the GETOPT functions
- X * that are on most systems, even TURBO-C has these.
- X */
- X#define USE_GETOPT /* Use the GETOPT package */
- Xint extract = 1; /* Extract contents */
- Xint debugging = 0; /* debug enable */
- Xint verbose = 0; /* be verbose */
- Xint list_zip = 0; /* list contents only */
- Xint test_zip = 0; /* test CRC's only */
- Xint unixfy = 1; /* Convert filename to lowercase */
- Xint dsp_comment = 1; /* Display comments */
- X
- Xlong crc32val; /* The CRC value we calculate */
- Xint numbad =0;
- Xint Total_files =0;
- Xlong Total_bytes =0;
- Xlong Total_length =0;
- X
- X/* ============================================================= */
- X
- Xint create_output_file()
- X /* return non-0 if creat failed */
- X{
- X if (!extract)
- X return 0;
- X
- X /* create the output file with READ and WRITE permissions */
- X outfd = creat(filename, S_IWRITE | S_IREAD);
- X if (outfd < 1) {
- X printf("Can't create output: %s\n", filename);
- X return 1;
- X }
- X
- X /*
- X * close the newly created file and reopen it in BINARY mode to
- X * disable all CR/LF translations
- X */
- X close(outfd);
- X outfd = open(filename, O_RDWR | O_BINARY);
- X
- X /* write a single byte at EOF to pre-allocate the file */
- X lseek(outfd, lrec.uncompressed_size - 1L, SEEK_SET);
- X write(outfd, "?", 1);
- X lseek(outfd, 0L, SEEK_SET);
- X return 0;
- X}
- X
- X
- Xint open_input_file()
- X /* return non-0 if creat failed */
- X{
- X /*
- X * open the zipfile for reading and in BINARY mode to prevent cr/lf
- X * translation, which would corrupt the bitstreams
- X */
- X
- X zipfd = open(zipfn, O_RDONLY | O_BINARY);
- X if (zipfd < 1) {
- X printf("Can't open input file: %s\n", zipfn);
- X return (1);
- X }
- X return 0;
- X}
- X
- X
- Xint FillBuffer()
- X /* fill input buffer if possible */
- X{
- X int readsize;
- X
- X if (lrec.compressed_size <= 0)
- X return incnt = 0;
- X
- X if (lrec.compressed_size > INBUFSIZ)
- X readsize = INBUFSIZ;
- X else
- X readsize = (int) lrec.compressed_size;
- X incnt = read(zipfd, inbuf, readsize);
- X
- X lrec.compressed_size -= incnt;
- X inptr = inbuf;
- X return incnt--;
- X}
- X
- Xint ReadByte(x)
- Xunsigned *x;
- X /* read a byte; return 8 if byte available, 0 if not */
- X{
- X if (incnt-- == 0)
- X if (FillBuffer() == 0)
- X return 0;
- X
- X *x = *inptr++;
- X return 8;
- X}
- X
- X
- X/* ------------------------------------------------------------- */
- Xstatic unsigned mask_bits[] =
- X {0, 0x0001, 0x0003, 0x0007, 0x000f,
- X 0x001f, 0x003f, 0x007f, 0x00ff,
- X 0x01ff, 0x03ff, 0x07ff, 0x0fff,
- X 0x1fff, 0x3fff, 0x7fff, 0xffff
- X };
- X
- X
- Xint FillBitBuffer(bits)
- Xregister int bits;
- X{
- X /* get the bits that are left and read the next word */
- X unsigned temp;
- X register int result = bitbuf;
- X int sbits = bits_left;
- X bits -= bits_left;
- X
- X /* read next word of input */
- X bits_left = ReadByte(&bitbuf);
- X bits_left += ReadByte(&temp);
- X bitbuf |= (temp << 8);
- X if (bits_left == 0)
- X zipeof = 1;
- X
- X /* get the remaining bits */
- X result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
- X bitbuf >>= bits;
- X bits_left -= bits;
- X return result;
- X}
- X
- X#define READBIT(nbits,zdest,ztype) \
- X { if (nbits <= bits_left) \
- X { zdest = ztype(bitbuf & mask_bits[nbits]);\
- X bitbuf >>= nbits; bits_left -= nbits; }\
- X else zdest = ztype(FillBitBuffer(nbits));}
- X
- X/*
- X * macro READBIT(nbits,zdest,ztype)
- X * {
- X * if (nbits <= bits_left) {
- X * zdest = ztype(bitbuf & mask_bits[nbits]);
- X * bitbuf >>= nbits;
- X * bits_left -= nbits;
- X * } else
- X * zdest = ztype(FillBitBuffer(nbits));
- X * }
- X *
- X */
- X
- X
- X/* ------------------------------------------------------------- */
- X
- Xvoid Write_file()
- X{
- X if (extract)
- X write(outfd, outbuf, outcnt);
- X}
- X
- X/* ------------------------------------------------------------- */
- X
- Xvoid FlushOutput()
- X /* flush contents of output buffer */
- X{
- X UpdateCRC(outbuf, outcnt);
- X Write_file();
- X outpos += outcnt;
- X outcnt = 0;
- X outptr = outbuf;
- X}
- X
- X#define OUTB(intc) { *outptr++=intc; if (++outcnt==OUTBUFSIZ) FlushOutput(); }
- X
- X/*
- X * macro OUTB(intc)
- X * {
- X * *outptr++=intc;
- X * if (++outcnt==OUTBUFSIZ)
- X * FlushOutput();
- X * }
- X *
- X */
- X
- X
- X/* ----------------------------------------------------------- */
- X
- Xvoid LoadFollowers()
- X{
- X register int x;
- X register int i;
- X
- X for (x = 255; x >= 0; x--) {
- X READBIT(6,Slen[x],(byte));
- X for (i = 0; i < Slen[x]; i++) {
- X READBIT(8,followers[x][i],(byte));
- X }
- X }
- X}
- X
- X/* ----------------------------------------------------------- */
- X/*
- X * The Reducing algorithm is actually a combination of two
- X * distinct algorithms. The first algorithm compresses repeated
- X * byte sequences, and the second algorithm takes the compressed
- X * stream from the first algorithm and applies a probabilistic
- X * compression method.
- X */
- X
- Xint L_table[] = {0, 0x7f, 0x3f, 0x1f, 0x0f};
- X
- Xint D_shift[] = {0, 0x07, 0x06, 0x05, 0x04};
- Xint D_mask[] = {0, 0x01, 0x03, 0x07, 0x0f};
- X
- Xint B_table[] = {8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
- X 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
- X 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- X 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
- X 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- X 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- X 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- X 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- X 8, 8, 8, 8};
- X
- X/* ----------------------------------------------------------- */
- X
- Xvoid unReduce()
- X /* expand probablisticly reduced data */
- X{
- X register int lchar;
- X int nchar;
- X int ExState;
- X int V;
- X int Len;
- X
- X factor = lrec.compression_method - 1;
- X ExState = 0;
- X lchar = 0;
- X LoadFollowers();
- X
- X while (((outpos + outcnt) < lrec.uncompressed_size) && (!zipeof)) {
- X if (Slen[lchar] == 0)
- X READBIT(8,nchar,(int)) /* ; */
- X else
- X {
- X READBIT(1,nchar,(int));
- X if (nchar != 0)
- X READBIT(8,nchar,(int)) /* ; */
- X else
- X {
- X int follower;
- X int bitsneeded = B_table[Slen[lchar]];
- X READBIT(bitsneeded,follower,(int));
- X nchar = followers[lchar][follower];
- X }
- X }
- X
- X /* expand the resulting byte */
- X switch (ExState) {
- X
- X case 0:
- X if (nchar != DLE)
- X OUTB(nchar) /*;*/
- X else
- X ExState = 1;
- X break;
- X
- X case 1:
- X if (nchar != 0) {
- X V = nchar;
- X Len = V & L_table[factor];
- X if (Len == L_table[factor])
- X ExState = 2;
- X else
- X ExState = 3;
- X }
- X else {
- X OUTB(DLE);
- X ExState = 0;
- X }
- X break;
- X
- X case 2: {
- X Len += nchar;
- X ExState = 3;
- X }
- X break;
- X
- X case 3: {
- X register int i = Len + 3;
- X int offset = (((V >> D_shift[factor]) &
- X D_mask[factor]) << 8) + nchar + 1;
- X longint op = outpos + outcnt - offset;
- X
- X /* special case- before start of file */
- X while ((op < 0L) && (i > 0)) {
- X OUTB(0);
- X op++;
- X i--;
- X }
- X
- X /* normal copy of data from output buffer */
- X {
- X register int ix = (int) (op % OUTBUFSIZ);
- X
- X /* do a block memory copy if possible */
- X if ( ((ix +i) < OUTBUFSIZ) &&
- X ((outcnt+i) < OUTBUFSIZ) ) {
- X memcpy(outptr,&outbuf[ix],i);
- X outptr += i;
- X outcnt += i;
- X }
- X
- X /* otherwise copy byte by byte */
- X else while (i--) {
- X OUTB(outbuf[ix]);
- X if (++ix >= OUTBUFSIZ)
- X ix = 0;
- X }
- X }
- X
- X ExState = 0;
- X }
- X break;
- X }
- X
- X /* store character for next iteration */
- X lchar = nchar;
- X }
- X}
- X
- X
- X/* ------------------------------------------------------------- */
- X/*
- X * Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm
- X * with partial clearing.
- X *
- X */
- X
- Xvoid partial_clear()
- X{
- X register int pr;
- X register int cd;
- X
- X /* mark all nodes as potentially unused */
- X for (cd = first_ent; cd < free_ent; cd++)
- X prefix_of[cd] |= 0x8000;
- X
- X /* unmark those that are used by other nodes */
- X for (cd = first_ent; cd < free_ent; cd++) {
- X pr = prefix_of[cd] & 0x7fff; /* reference to another node? */
- X if (pr >= first_ent) /* flag node as referenced */
- X prefix_of[pr] &= 0x7fff;
- X }
- X
- X /* clear the ones that are still marked */
- X for (cd = first_ent; cd < free_ent; cd++)
- X if ((prefix_of[cd] & 0x8000) != 0)
- X prefix_of[cd] = -1;
- X
- X /* find first cleared node as next free_ent */
- X cd = first_ent;
- X while ((cd < maxcodemax) && (prefix_of[cd] != -1))
- X cd++;
- X free_ent = cd;
- X}
- X
- X
- X/* ------------------------------------------------------------- */
- X
- Xvoid unShrink()
- X{
- X#define GetCode(dest) READBIT(codesize,dest,(int))
- X
- X register int code;
- X register int stackp;
- X int finchar;
- X int oldcode;
- X int incode;
- X
- X
- X /* decompress the file */
- X maxcodemax = 1 << max_bits;
- X codesize = init_bits;
- X maxcode = (1 << codesize) - 1;
- X free_ent = first_ent;
- X offset = 0;
- X sizex = 0;
- X
- X for (code = maxcodemax; code > 255; code--)
- X prefix_of[code] = -1;
- X
- X for (code = 255; code >= 0; code--) {
- X prefix_of[code] = 0;
- X suffix_of[code] = code;
- X }
- X
- X GetCode(oldcode);
- X if (zipeof)
- X return;
- X finchar = oldcode;
- X
- X OUTB(finchar);
- X
- X stackp = hsize;
- X
- X while (!zipeof) {
- X GetCode(code);
- X if (zipeof)
- X return;
- X
- X while (code == clear) {
- X GetCode(code);
- X switch (code) {
- X
- X case 1:{
- X codesize++;
- X if (codesize == max_bits)
- X maxcode = maxcodemax;
- X else
- X maxcode = (1 << codesize) - 1;
- X }
- X break;
- X
- X case 2:
- X partial_clear();
- X break;
- X }
- X
- X GetCode(code);
- X if (zipeof)
- X return;
- X }
- X
- X
- X /* special case for KwKwK string */
- X incode = code;
- X if (prefix_of[code] == -1) {
- X stack[--stackp] = finchar;
- X code = oldcode;
- X }
- X
- X
- X /* generate output characters in reverse order */
- X while (code >= first_ent) {
- X stack[--stackp] = suffix_of[code];
- X code = prefix_of[code];
- X }
- X
- X finchar = suffix_of[code];
- X stack[--stackp] = finchar;
- X
- X
- X /* and put them out in forward order, block copy */
- X if ((hsize-stackp+outcnt) < OUTBUFSIZ) {
- X memcpy(outptr,&stack[stackp],hsize-stackp);
- X outptr += hsize-stackp;
- X outcnt += hsize-stackp;
- X stackp = hsize;
- X }
- X
- X /* output byte by byte if we can't go by blocks */
- X else while (stackp < hsize)
- X OUTB(stack[stackp++]);
- X
- X
- X /* generate new entry */
- X code = free_ent;
- X if (code < maxcodemax) {
- X prefix_of[code] = oldcode;
- X suffix_of[code] = finchar;
- X
- X do
- X code++;
- X while ((code < maxcodemax) && (prefix_of[code] != -1));
- X
- X free_ent = code;
- X }
- X
- X /* remember previous code */
- X oldcode = incode;
- X }
- X
- X}
- X
- X/* ------------------------------------------------------------- */
- X/*
- X * Imploding
- X * ---------
- X *
- X * The Imploding algorithm is actually a combination of two distinct
- X * algorithms. The first algorithm compresses repeated byte sequences
- X * using a sliding dictionary. The second algorithm is used to compress
- X * the encoding of the sliding dictionary ouput, using multiple
- X * Shannon-Fano trees.
- X *
- X */
- X
- X#define maxSF 256
- X
- X typedef struct sf_entry {
- X word Code;
- X byte Value;
- X byte BitLength;
- X } sf_entry;
- X
- X typedef struct sf_tree { /* a shannon-fano tree */
- X sf_entry entry[maxSF];
- X int entries;
- X int MaxLength;
- X } sf_tree;
- X
- X typedef sf_tree *sf_treep;
- X
- X sf_tree lit_tree;
- X sf_tree length_tree;
- X sf_tree distance_tree;
- X boolean lit_tree_present;
- X boolean eightK_dictionary;
- X int minimum_match_length;
- X int dict_bits;
- X
- X
- Xvoid SortLengths(tree)
- Xsf_tree *tree;
- X /* Sort the Bit Lengths in ascending order, while retaining the order
- X of the original lengths stored in the file */
- X{
- X int x;
- X int gap;
- X sf_entry t;
- X boolean noswaps;
- X int a, b;
- X
- X gap = tree->entries / 2;
- X
- X do {
- X do {
- X noswaps = 1;
- X for (x = 0; x <= (tree->entries - 1) - gap; x++)
- X {
- X a = tree->entry[x].BitLength;
- X b = tree->entry[x + gap].BitLength;
- X if ((a > b) || ((a == b) && (tree->entry[x].Value > tree->entry[x + gap].Value)))
- X {
- X t = tree->entry[x];
- X tree->entry[x] = tree->entry[x + gap];
- X tree->entry[x + gap] = t;
- X noswaps = 0;
- X }
- X }
- X } while (!noswaps);
- X
- X gap = gap / 2;
- X } while (gap > 0);
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- Xvoid ReadLengths(tree)
- Xsf_tree *tree;
- X{
- X int treeBytes;
- X int i;
- X int num, len;
- X
- X /* get number of bytes in compressed tree */
- X READBIT(8,treeBytes,(int));
- X treeBytes++;
- X i = 0;
- X
- X tree->MaxLength = 0;
- X
- X /* High 4 bits: Number of values at this bit length + 1. (1 - 16)
- X Low 4 bits: Bit Length needed to represent value + 1. (1 - 16) */
- X while (treeBytes > 0)
- X {
- X READBIT(4,len,(int)); len++;
- X READBIT(4,num,(int)); num++;
- X
- X while (num > 0)
- X {
- X if (len > tree->MaxLength)
- X tree->MaxLength = len;
- X tree->entry[i].BitLength = (byte) len;
- X tree->entry[i].Value = (byte) i;
- X i++;
- X num--;
- X }
- X
- X treeBytes--;
- X }
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- Xvoid GenerateTrees(tree)
- Xsf_tree *tree;
- X /* Generate the Shannon-Fano trees */
- X{
- X word Code;
- X int CodeIncrement;
- X int LastBitLength;
- X int i;
- X
- X
- X Code = 0;
- X CodeIncrement = 0;
- X LastBitLength = 0;
- X
- X i = tree->entries - 1; /* either 255 or 63 */
- X while (i >= 0)
- X {
- X Code += CodeIncrement;
- X if (tree->entry[i].BitLength != (byte) LastBitLength)
- X {
- X LastBitLength = tree->entry[i].BitLength;
- X CodeIncrement = 1 << (16 - LastBitLength);
- X }
- X
- X tree->entry[i].Code = Code;
- X i--;
- X }
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- Xvoid ReverseBits(tree)
- Xsf_tree *tree;
- X /* Reverse the order of all the bits in the above ShannonCode[]
- X vector, so that the most significant bit becomes the least
- X significant bit. For example, the value 0x1234 (hex) would become
- X 0x2C48 (hex). */
- X{
- X int i;
- X word mask;
- X word revb;
- X word v;
- X word o;
- X int b;
- X
- X
- X for (i = 0; i <= tree->entries - 1; i++)
- X {
- X /* get original code */
- X o = tree->entry[i].Code;
- X
- X /* reverse each bit */
- X mask = 0x0001;
- X revb = 0x8000;
- X v = 0;
- X for (b = 0; b <= 15; b++)
- X {
- X /* if bit set in mask, then substitute reversed bit */
- X if ((o & mask) != 0)
- X v = v | revb;
- X
- X /* advance to next bit */
- X revb = (revb >> 1);
- X mask = (mask << 1);
- X }
- X
- X /* store reversed bits */
- X tree->entry[i].Code = v;
- X }
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- Xvoid LoadTree(tree, treesize)
- Xsf_tree *tree;
- Xint treesize;
- X /* allocate and load a shannon-fano tree from the compressed file */
- X{
- X tree->entries = treesize;
- X ReadLengths(tree);
- X SortLengths(tree);
- X GenerateTrees(tree);
- X ReverseBits(tree);
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- Xvoid LoadTrees()
- X{
- X /* bit 1... */
- X eightK_dictionary = (boolean) ((lrec.general_purpose_bit_flag & 0x02) != 0);
- X /* bit 2... */
- X lit_tree_present = (boolean) ((lrec.general_purpose_bit_flag & 0x04) != 0);
- X
- X if (eightK_dictionary)
- X dict_bits = 7;
- X else
- X dict_bits = 6;
- X
- X if (lit_tree_present)
- X {
- X minimum_match_length = 3;
- X LoadTree(&lit_tree,256);
- X }
- X else
- X minimum_match_length = 2;
- X
- X LoadTree(&length_tree,64);
- X LoadTree(&distance_tree,64);
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- Xvoid ReadTree(tree, dest)
- Xsf_tree *tree;
- Xint *dest;
- X /* read next byte using a shannon-fano tree */
- X{
- X int bits = 0;
- X word cv = 0;
- X int cur = 0;
- X int b;
- X
- X *dest = -1; /* in case of error */
- X
- X for (;;)
- X {
- X READBIT(1,b,(int));
- X cv = cv | (b << bits);
- X bits++;
- X
- X /* this is a very poor way of decoding shannon-fano. two quicker
- X methods come to mind:
- X a) arrange the tree as a huffman-style binary tree with
- X a "leaf" indicator at each node,
- X and
- X b) take advantage of the fact that s-f codes are at most 8
- X bits long and alias unused codes for all bits following
- X the "leaf" bit.
- X */
- X
- X while (tree->entry[cur].BitLength < (byte) bits)
- X {
- X cur++;
- X if (cur >= tree->entries)
- X return; /* data error */
- X }
- X
- X while (tree->entry[cur].BitLength == (byte) bits)
- X {
- X if (tree->entry[cur].Code == cv)
- X {
- X *dest = tree->entry[cur].Value;
- X return;
- X }
- X
- X cur++;
- X if (cur >= tree->entries)
- X return; /* data error */
- X }
- X }
- X}
- X
- X
- X/* ----------------------------------------------------------- */
- X
- Xvoid unImplode()
- X /* expand imploded data */
- X
- X{
- X int lout;
- X longint op;
- X int Length;
- X int Distance;
- X
- X LoadTrees();
- X
- X while ((!zipeof) && ((outpos+outcnt) < lrec.uncompressed_size))
- X {
- X READBIT(1,lout,(int));
- X
- X if (lout != 0) /* encoded data is literal data */
- X {
- X if (lit_tree_present) /* use Literal Shannon-Fano tree */
- X ReadTree(&lit_tree,&lout);
- X else
- X READBIT(8,lout,(int));
- X
- X OUTB((byte) lout);
- X }
- X else /* encoded data is sliding dictionary match */
- X {
- X READBIT(dict_bits,lout,(int));
- X Distance = lout;
- X
- X ReadTree(&distance_tree,&lout);
- X Distance |= (lout << dict_bits);
- X /* using the Distance Shannon-Fano tree, read and decode the
- X upper 6 bits of the Distance value */
- X
- X ReadTree(&length_tree,&Length);
- X /* using the Length Shannon-Fano tree, read and decode the
- X Length value */
- X
- X Length += minimum_match_length;
- X if (Length == (63 + minimum_match_length))
- X {
- X READBIT(8,lout,(int));
- X Length += lout;
- X }
- X
- X /* move backwards Distance+1 bytes in the output stream, and copy
- X Length characters from this position to the output stream.
- X (if this position is before the start of the output stream,
- X then assume that all the data before the start of the output
- X stream is filled with zeros) */
- X
- X op = (outpos+outcnt) - Distance - 1L;
- X
- X /* special case- before start of file */
- X while ((op < 0L) && (Length > 0)) {
- X OUTB(0);
- X op++;
- X Length--;
- X }
- X
- X /* normal copy of data from output buffer */
- X {
- X register int ix = (int) (op % OUTBUFSIZ);
- X
- X /* do a block memory copy if possible */
- X if ( ((ix +Length) < OUTBUFSIZ) &&
- X ((outcnt+Length) < OUTBUFSIZ) ) {
- X memcpy(outptr,&outbuf[ix],Length);
- X outptr += Length;
- X outcnt += Length;
- X }
- X
- X /* otherwise copy byte by byte */
- X else while (Length--) {
- X OUTB(outbuf[ix]);
- X if (++ix >= OUTBUFSIZ)
- X ix = 0;
- X }
- X }
- X }
- X }
- X}
- X
- X/* ---------------------------------------------------------- */
- X
- Xvoid extract_member()
- X{
- X unsigned b;
- X
- X bits_left = 0;
- X bitbuf = 0;
- X incnt = 0;
- X outpos = 0L;
- X outcnt = 0;
- X outptr = outbuf;
- X zipeof = 0;
- X crc32val = 0xFFFFFFFFL;
- X
- X
- X /* create the output file with READ and WRITE permissions */
- X if (create_output_file())
- X exit(1);
- X
- X switch (lrec.compression_method) {
- X
- X case 0: /* stored */
- X {
- X if (test_zip)
- X printf("Testing: %-12s ", filename);
- X if (extract)
- X printf(" Extracting: %-12s ", filename);
- X while (ReadByte(&b))
- X OUTB(b);
- X }
- X break;
- X
- X case 1: { /* shrunk */
- X if (test_zip)
- X printf("Testing: %-12s ", filename);
- X if (extract)
- X printf("UnShrinking: %-12s ", filename);
- X unShrink();
- X }
- X break;
- X
- X case 2: /* reduced, factor:1 */
- X case 3: /* reduced, factor:2 */
- X case 4: /* reduced, factor:3 */
- X case 5: { /* reduced, factor:4 */
- X if (test_zip)
- X printf("Testing: %-12s ", filename);
- X if (extract)
- X printf(" Expanding: %-12s ", filename);
- X unReduce();
- X }
- X break;
- X
- X case 6: { /* imploded */
- X if (test_zip)
- X printf("Testing: %-12s ", filename);
- X if (extract)
- X printf(" Exploding: %-12s ", filename);
- X unImplode();
- X }
- X break;
- X
- X
- X default:
- X printf("Unknown compression method.");
- X }
- X
- X
- X /* write the last partial buffer, if any */
- X if (outcnt > 0) {
- X UpdateCRC(outbuf, outcnt);
- X Write_file();
- X }
- X
- X /* set output file date and time */
- X set_file_time();
- X
- X close(outfd);
- X
- X crc32val = -1 - crc32val;
- X if (!list_zip) {
- X if (crc32val != lrec.crc32) {
- X numbad++;
- X printf(" Bad");
- X if(verbose)
- X printf(", CRC %08lx (should be %08lx)", lrec.crc32, crc32val);
- X } else {
- X printf(" Ok");
- X if (verbose)
- X printf(", CRC = %08lx", lrec.crc32);
- X }
- X printf("\n");
- X }
- X}
- X
- X
- X/* ---------------------------------------------------------- */
- X
- Xvoid get_string(len, s)
- Xint len;
- Xchar *s;
- X{
- X read(zipfd, s, len);
- X s[len] = 0;
- X}
- X
- X/* UNIX support routines: Michael Enkelis */
- Xget_byte()
- X{
- X byte nibble;
- X read(zipfd,&nibble,1);
- X return (byte) (nibble & 0xff);
- X}
- X
- Xget_word()
- X{
- X byte nibble[2];
- X nibble[0] = get_byte();
- X nibble[1] = get_byte();
- X return (word) (nibble[0] | nibble[1] << 8);
- X}
- X
- Xget_long()
- X{
- X byte nibble[4];
- X nibble[0] = get_byte();
- X nibble[1] = get_byte();
- X nibble[2] = get_byte();
- X nibble[3] = get_byte();
- X return (longint) ((unsigned long) nibble[0] |
- X ((unsigned long) nibble[1] << 8) |
- X ((unsigned long) nibble[2] << 16) |
- X ((unsigned long) nibble[3] << 24));
- X}
- X/** End of added support routines **/
- X
- X
- X/* ---------------------------------------------------------- */
- X
- Xvoid process_local_file_header()
- X{
- X byte Temp;
- X byte yr, mo, dy; /* parts of a date */
- X byte hh, mm, ss; /* parts of a time */
- X
- X static char *mon[] = /* month abbreviations */
- X {
- X "Jan", "Feb", "Mar", "Apr",
- X "May", "Jun", "Jul", "Aug",
- X "Sep", "Oct", "Nov", "Dec"
- X };
- X
- X lrec.version_needed_to_extract = get_word();
- X lrec.general_purpose_bit_flag = get_word();
- X lrec.compression_method = get_word();
- X lrec.last_mod_file_time = get_word();
- X lrec.last_mod_file_date = get_word();
- X lrec.crc32 = get_long();
- X lrec.compressed_size = get_long();
- X lrec.uncompressed_size = get_long();
- X lrec.filename_length = get_word();
- X lrec.extra_field_length = get_word();
- X
- X get_string(lrec.filename_length,filename);
- X if (unixfy) {
- X char *cp;
- X for (cp = filename; *cp; ++cp)
- X if (isupper(*cp)) *cp = tolower(*cp);
- X }
- X
- X get_string(lrec.extra_field_length,extra);
- X
- X yr = (lrec.last_mod_file_date >> 9) & 0x7f; /* dissect the date */
- X mo = (lrec.last_mod_file_date >> 5) & 0x0f;
- X dy = lrec.last_mod_file_date & 0x1f;
- X
- X hh = (lrec.last_mod_file_time >> 11) & 0x1f; /* dissect the time */
- X mm = (lrec.last_mod_file_time >> 5) & 0x3f;
- X ss = (lrec.last_mod_file_time & 0x1f) * 2;
- X
- X if (debugging) {
- X printf("\n\nProcess LOCAL file header.\n");
- X Temp = lrec.version_needed_to_extract;
- X printf("Version used : %d.%d\n",Temp/10,Temp%10);
- X printf("Bit flags : ");
- X Temp = (lrec.general_purpose_bit_flag & 3);
- X if (Temp & 1)
- X printf("Encrypted\n");
- X if (lrec.compression_method == 6) {
- X printf("%dK sliding dictionary, ", (Temp & 2)? 8 : 4);
- X printf("%d Shannon-Fano trees", (Temp & 4)? 3 : 2);
- X }
- X printf("\n");
- X
- X printf("Compression : %d\n",lrec.compression_method);
- X printf("Mod time :");
- X printf("%2d:%02d%cm\n",
- X (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a'));
- X printf("Mod date :");
- X printf("%2d %3s %02d\n", dy, mon[mo - 1], (yr + 80) % 100);
- X printf("Crc32 : %d\n",~lrec.crc32);
- X printf("Compressed size : %d\n",lrec.compressed_size);
- X printf("Normal file size: %d\n",lrec.uncompressed_size);
- X printf("File name : %s.%s\n",filename,extra);
- X }
- X
- X extract_member();
- X}
- X
- X
- X/* ---------------------------------------------------------- */
- X
- Xvoid process_central_file_header()
- X{
- X central_directory_file_header rec;
- X char filename[STRSIZ];
- X char extra[STRSIZ];
- X
- X byte Temp;
- X byte yr, mo, dy; /* parts of a date */
- X byte hh, mm, ss; /* parts of a time */
- X
- X static char *mon[] = /* month abbreviations */
- X {
- X "Jan", "Feb", "Mar", "Apr",
- X "May", "Jun", "Jul", "Aug",
- X "Sep", "Oct", "Nov", "Dec"
- X };
- X
- X rec.version_made_by = get_word();
- X rec.version_needed_to_extract = get_word();
- X rec.general_purpose_bit_flag = get_word();
- X rec.compression_method = get_word();
- X rec.last_mod_file_time = get_word();
- X rec.last_mod_file_date = get_word();
- X rec.crc32 = get_long();
- X rec.compressed_size = get_long();
- X rec.uncompressed_size = get_long();
- X rec.filename_length = get_word();
- X rec.extra_field_length = get_word();
- X rec.file_comment_length = get_word();
- X rec.disk_number_start = get_word();
- X rec.internal_file_attributes = get_word();
- X rec.external_file_attributes = get_long();
- X rec.relative_offset_local_header = get_long();
- X
- X get_string(rec.filename_length,filename);
- X if (unixfy) {
- X char *cp;
- X for (cp = filename; *cp; ++cp)
- X if (isupper(*cp)) *cp = tolower(*cp);
- X }
- X
- X get_string(rec.extra_field_length,extra);
- X comment = (byte *) (realloc(comment, rec.file_comment_length));
- X get_string(rec.file_comment_length,comment);
- X
- X yr = (rec.last_mod_file_date >> 9) & 0x7f; /* dissect the date */
- X mo = (rec.last_mod_file_date >> 5) & 0x0f;
- X dy = rec.last_mod_file_date & 0x1f;
- X
- X hh = (rec.last_mod_file_time >> 11) & 0x1f; /* dissect the time */
- X mm = (rec.last_mod_file_time >> 5) & 0x3f;
- X ss = (rec.last_mod_file_time & 0x1f) * 2;
- X
- X if (debugging) {
- X printf("\n\nProcess CENTRAL file header.\n");
- X printf("Version made by : ");
- X Temp = rec.version_made_by;
- X switch ((Temp >> 8) & 7) {
- X case 0: printf("MS-DOS");break;
- X case 1: printf("Amiga");break;
- X case 2: printf("VMS");break;
- X case 3: printf("Unix");break;
- X case 4: printf("VM/CMS");break;
- X case 5: printf("Atari");break;
- X case 6: printf("OS/2");break;
- X case 7: printf("Macintosh");break;
- X default:
- X printf("Unknown");
- X }
- X printf(" Version %d.%d\n",(Temp & 255)/10,(Temp & 255) % 10);
- X
- X printf("Ver to extract : %d\n",rec.version_needed_to_extract);
- X printf("Bit flags : ");
- X Temp = (rec.general_purpose_bit_flag & 3);
- X if (Temp & 1)
- X printf("Encrypted\n");
- X if (rec.compression_method == 6) {
- X printf("%dK sliding dictionary, ", (Temp & 2)? 8 : 4);
- X printf("%d Shannon-Fano trees", (Temp & 4)? 3 : 2);
- X }
- X printf("\n");
- X
- X printf("Compression : %d\n",rec.compression_method);
- X printf("Mod time :");
- X printf("%2d:%02d%cm\n",
- X (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a'));
- X printf("Mod date :");
- X printf("%2d %3s %02d\n", dy, mon[mo - 1], (yr + 80) % 100);
- X printf("Crc32 : %d\n",~rec.crc32);
- X printf("Compressed size : %d\n",rec.compressed_size);
- X printf("Normal file size: %d\n",rec.uncompressed_size);
- X printf("File name : %s.%s\n",filename,extra);
- X printf("Comment size : %d\n",rec.file_comment_length);
- X printf("Disk start # : %d\n",rec.disk_number_start);
- X printf("File attributes : %d\n",rec.internal_file_attributes);
- X printf("Os attributes : %d\n",rec.external_file_attributes);
- X printf("Offset to header: %d\n",rec.relative_offset_local_header);
- X printf("Comment : %s\n",comment);
- X }
- X
- X if (list_zip) {
- X Total_files++;
- X Total_bytes += rec.uncompressed_size;
- X Total_length += rec.compressed_size;
- X
- X printf("%-12s %8d ", filename,rec.uncompressed_size);
- X if (verbose) {
- X printf("%8d ",rec.compressed_size);
- X if (rec.compressed_size)
- X printf("%3d%% ",100L - (100L * rec.compressed_size)/
- X rec.uncompressed_size);
- X else
- X printf("--- ");
- X }
- X
- X printf("%2d %3s %02d", dy, mon[mo - 1], (yr + 80) % 100);
- X
- X if (verbose)
- X printf(" %2d:%02d%cm",
- X (hh > 12 ? hh - 12 : hh), mm, (hh > 11 ? 'p' : 'a'));
- X printf("\n");
- X }
- X
- X}
- X
- X
- X/* ---------------------------------------------------------- */
- X
- Xvoid process_end_central_dir()
- X{
- X end_central_dir_record rec;
- X
- X rec.number_this_disk = get_word();
- X rec.number_disk_with_start_central_directory = get_word();
- X rec.total_entries_central_dir_on_this_disk = get_word();
- X rec.total_entries_central_dir = get_word();
- X rec.size_central_directory = get_long();
- X rec.offset_start_central_directory = get_long();
- X rec.zipfile_comment_length = get_word();
- X
- X comment = (byte *) (realloc(comment, rec.zipfile_comment_length));
- X get_string(rec.zipfile_comment_length,comment);
- X
- X if (debugging) {
- X printf("\n\nProcess END_CENTRAL directory header.\n");
- X printf("This disk : %d\n",rec.number_this_disk);
- X printf("Starting disk : %d\n",
- X rec.number_disk_with_start_central_directory);
- X printf("Total this disk : %d\n",
- X rec.total_entries_central_dir_on_this_disk);
- X printf("Total entries : %d\n",rec.total_entries_central_dir);
- X printf("Central dir size: %d\n",rec.size_central_directory);
- X printf("Offset to dir : %d\n",rec.offset_start_central_directory);
- X printf("Comment size : %d\n",rec.zipfile_comment_length);
- X printf("Comment : %s\n",comment);
- X }
- X}
- X
- X
- X/* ---------------------------------------------------------- */
- X
- Xvoid process_headers()
- X{
- X int i;
- X char sig[4];
- X
- X if (list_zip) {
- X if (verbose) {
- X printf("\nName Length Size now SF Date Time");
- X printf("\n============ ======== ======== ==== ========= ========\n");
- X } else {
- X printf("\nName Length Date");
- X printf("\n============ ======== =========\n");
- X }
- X }
- X
- X while (1)
- X {
- X for (i=0; i<4; i++) /* Read the ZIP file sig */
- X sig[i] = get_byte();
- X
- X if (strncmp(sig,local_file_header_signature,4) == 0)
- X process_local_file_header();
- X else
- X if (strncmp(sig,central_file_header_signature,4) == 0)
- X process_central_file_header();
- X else
- X if (strncmp(sig,end_central_dir_signature,4) == 0)
- X {
- X process_end_central_dir();
- X if (test_zip) {
- X if (numbad < 1)
- X printf("No errors detected\n");
- X else
- X if (numbad == 1)
- X printf("One error detected\n");
- X else
- X printf("%d errors detected\n",numbad);
- X }
- X if (list_zip) {
- X if (verbose) {
- X printf(" ==== ======== ======== ==== \n");
- X printf("Total: %4d %8d %8d ",
- X Total_files,Total_bytes,Total_length);
- X if (Total_length)
- X printf("%3d%%\n", 100 - (100 * Total_length)/
- X Total_bytes);
- X else
- X printf("---\n");
- X } else {
- X printf(" ==== ========\n");
- X printf("Total: %4d %8d\n",
- X Total_files,Total_bytes);
- X }
- X }
- X if (strlen(comment) && dsp_comment)
- X printf("%s\n",comment);
- X return;
- X }
- X else
- X {
- X printf("Invalid Zipfile Header\n");
- X return;
- X }
- X }
- X}
- X
- X
- X
- X/* ---------------------------------------------------------- */
- X
- Xvoid extract_zipfile()
- X{
- X /*
- X * open the zipfile for reading and in BINARY mode to prevent cr/lf
- X * translation, which would corrupt the bitstreams
- X */
- X
- X if (open_input_file())
- X exit(1);
- X
- X process_headers();
- X
- X close(zipfd);
- X}
- X
- X
- X/* ---------------------------------------------------------- */
- X/*
- X * main program
- X *
- X */
- X
- Xvoid main(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X
- X#ifdef USE_GETOPT
- X int c; /* next option letter */
- X int count = 0; /* count of required options seen */
- X
- X extern int optind; /* from getopt: next arg to process */
- X extern int opterr; /* used by getopt */
- X extern char *optarg;
- X
- X opterr = 0; /* so getopt won't print err msg */
- X
- X while ((c = getopt (argc, argv, "cdltuv")) != EOF)
- X {
- X switch (c) {
- X case 'c': dsp_comment =0; break;
- X case 'd': debugging++;dsp_comment =0; break;
- X case 'l': list_zip =1;extract =0; break;
- X case 't': test_zip =1;extract =0; break;
- X case 'u': unixfy =0; break;
- X case 'v': verbose++; break;
- X default: short_help();
- X }
- X }
- X
- X if (argv[optind] != NULL)
- X strcpy(zipfn,argv[optind]);
- X else
- X long_help();
- X
- X /* .ZIP default if none provided by user */
- X if (strchr(zipfn,'.') == NULL)
- X strcat(zipfn,".zip");
- X#else
- X if (argc != 2)
- X long_help();
- X
- X /* .ZIP default if none provided by user */
- X strcpy(zipfn, argv[1]);
- X if (strchr(zipfn, '.') == NULL)
- X strcat(zipfn, ".zip");
- X#endif
- X
- X /* allocate i/o buffers */
- X inbuf = (byte *) (malloc(INBUFSIZ));
- X outbuf = (byte *) (malloc(OUTBUFSIZ));
- X comment = (byte *) (malloc(STRSIZ));
- X if ((inbuf == NULL) || (outbuf == NULL) || (comment == NULL)) {
- X printf("Can't allocate buffers!\n");
- X exit(1);
- X }
- X
- X /* do the job... */
- X extract_zipfile();
- X exit(0);
- X}
- X
- Xlong_help()
- X{
- Xprintf("\nUnZip: Zipfile Extract Version:%s Patchlevel:%d",VERSION,PATCH);
- Xprintf("; (C) 1989 Samuel H. Smith\n");
- Xprintf("Courtesy of: S.H.Smith and The Tool Shop BBS, (602) 279-2673.");
- Xprintf("\n\n");
- Xprintf("UNIX mods by: Michael Enkelis\n\n");
- Xprintf("You may copy and distribute this program freely, provided that:\n");
- Xprintf(" 1) No fee is charged for such copying and distribution, and\n");
- Xprintf(" 2) It is distributed ONLY in its original, unmodified state.");
- Xprintf("\n\n");
- Xprintf("If you wish to distribute a modified version of this program, you MUST\n");
- Xprintf("include the source code.\n\n");
- Xprintf("If you modify this program, I would appreciate a copy of the new source\n");
- Xprintf("code. I am holding the copyright on the source code, so please don't\n");
- Xprintf("delete my name from the program files or from the documentation.\n\n");
- Xprintf("IN NO EVENT WILL I BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST\n");
- Xprintf("PROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES\n");
- Xprintf("ARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR FOR ANY\n");
- Xprintf("CLAIM BY ANY OTHER PARTY.\n\n");
- Xshort_help();
- Xexit(1);
- X}
- X
- Xshort_help()
- X{
- X printf("Usage: UnZip -chltuv FILE[.zip]\n\n");
- X printf(" -c Don't display coments.\n");
- X printf(" -h This help listing.\n");
- X printf(" -l List zip archive.\n");
- X printf(" -t Test zip archive.\n");
- X printf(" -u Don't convert filenames to lowercase.\n");
- X printf(" -v Verbose output.\n\n");
- X exit(1);
- X}
- SHAR_EOF
- if test 42309 -ne "`wc -c < 'unzipbsd.c'`"
- then
- echo shar: error transmitting "'unzipbsd.c'" '(should have been 42309 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'crc32.c'" '(7120 characters)'
- if test -f 'crc32.c'
- then
- echo shar: will not over-write existing file "'crc32.c'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'crc32.c'
- X
- X /* ============================================================= */
- X /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */
- X /* code or tables extracted from it, as desired without restriction. */
- X /* */
- X /* First, the polynomial itself and its table of feedback terms. The */
- X /* polynomial is */
- X /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
- X /* */
- X /* Note that we take it "backwards" and put the highest-order term in */
- X /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
- X /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
- X /* the MSB being 1. */
- X /* */
- X /* Note that the usual hardware shift register implementation, which */
- X /* is what we're using (we're merely optimizing it by doing eight-bit */
- X /* chunks at a time) shifts bits into the lowest-order term. In our */
- X /* implementation, that means shifting towards the right. Why do we */
- X /* do it this way? Because the calculated CRC must be transmitted in */
- X /* order from highest-order term to lowest-order term. UARTs transmit */
- X /* characters in order from LSB to MSB. By storing the CRC this way, */
- X /* we hand it to the UART in the order low-byte to high-byte; the UART */
- X /* sends each low-bit to hight-bit; and the result is transmission bit */
- X /* by bit from highest- to lowest-order term without requiring any bit */
- X /* shuffling on our part. Reception works similarly. */
- X /* */
- X /* The feedback terms table consists of 256, 32-bit entries. Notes: */
- X /* */
- X /* The table can be generated at runtime if desired; code to do so */
- X /* is shown later. It might not be obvious, but the feedback */
- X /* terms simply represent the results of eight shift/xor opera- */
- X /* tions for all combinations of data and CRC register values. */
- X /* */
- X /* The values must be right-shifted by eight bits by the "updcrc" */
- X /* logic; the shift must be unsigned (bring in zeroes). On some */
- X /* hardware you could probably optimize the shift in assembler by */
- X /* using byte-swap instructions. */
- X /* polynomial $edb88320 */
- X /* */
- X /* -------------------------------------------------------------------- */
- X
- Xlong crc_32_tab[] = {
- X 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
- X 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
- X 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
- X 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
- X 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
- X 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
- X 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
- X 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
- X 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
- X 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
- X 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
- X 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
- X 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
- X 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
- X 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
- X 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
- X 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
- X 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
- X 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
- X 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
- X 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
- X 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
- X 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
- X 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
- X 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
- X 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
- X 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
- X 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
- X 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
- X 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
- X 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
- X 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
- X 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
- X 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
- X 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
- X 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
- X 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
- X 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
- X 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
- X 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
- X 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
- X 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
- X 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
- X 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
- X 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
- X 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
- X 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
- X 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
- X 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
- X 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
- X 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
- X 0x2d02ef8dL
- X };
- X
- X/* ------------------------------------------------------------- */
- X
- Xextern long crc32val;
- X
- Xvoid UpdateCRC(s, len)
- Xregister char *s;
- Xregister int len;
- X /* update running CRC calculation with contents of a buffer */
- X{
- X int i;
- X for (i = 0; i < len; i ++) {
- X crc32val = crc_32_tab[(int) ((crc32val) ^ (s[i])) & 0xff] ^
- X (((crc32val) >> 8) & 0x00FFFFFFL);
- X }
- X}
- SHAR_EOF
- if test 7120 -ne "`wc -c < 'crc32.c'`"
- then
- echo shar: error transmitting "'crc32.c'" '(should have been 7120 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'patchlevel.h'" '(16 characters)'
- if test -f 'patchlevel.h'
- then
- echo shar: will not over-write existing file "'patchlevel.h'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'patchlevel.h'
- X#define PATCH 0
- SHAR_EOF
- if test 16 -ne "`wc -c < 'patchlevel.h'`"
- then
- echo shar: error transmitting "'patchlevel.h'" '(should have been 16 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'unzip.doc'" '(3086 characters)'
- if test -f 'unzip.doc'
- then
- echo shar: will not over-write existing file "'unzip.doc'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'unzip.doc'
- X
- X UnZip
- X
- X Version 2.0.1, 09-16-89
- X
- X Zipfile Extract Utility
- X
- X Copyright (C) 1989 Samuel H. Smith; ALL RIGHTS RESERVED
- X
- X
- X'UnZip' is a small Zipfile extract utility. It is written to be as
- Xsmall and portable as possible -- ideal as a starting point for handling
- X.ZIP files in non-IBM environments.
- X
- XSource code is provided in C and Turbo Pascal. If you port this program
- Xto a non-IBM system, I would appreciate a copy of the ported source and
- Xexec files.
- X
- X
- XUsage
- X-----
- X unz filename[.zip] ;pascal language version
- X unzip filename[.zip] ;C language version
- X
- X
- XRevision history
- X----------------
- X
- X3-3-89
- X Initial alpha test release.
- X
- X3-5-89
- X First fully operational release. Does not implement CRC verification,
- X but should correctly unzip all compression methods.
- X
- X3-6-89
- X Corrected end-of-file detection in both shrink and reduce expanders.
- X Resulting files should now always have the correct size. Added ".ZIP"
- X default to unzip.c to match calling conventions of unz.pas.
- X
- X3-8-89
- X Moved machine and operating-system specific code to a block starting
- X around line 180. Added code to swap bytes on host machines that
- X store the high order bytes in lower address locations than the low
- X order bytes.
- X
- X3-15-89
- X Added CRC checking in UNZIP.C. Speeded operation by about 150%.
- X
- X I'm spending my time on the C version now and don't plan to do any
- X further work on the pascal. If you're using the pascal version
- X please contact me.
- X
- X9-9-89
- X Addition of new "un-implode" logic to handle new compression format
- X included with PKZ101.
- X
- X
- X
- XLICENSE
- X=======
- X
- XYou may copy and distribute this program freely, provided that:
- X 1) No fee is charged for such copying and distribution, and
- X 2) It is distributed ONLY in its original, unmodified state.
- X
- XIf you wish to distribute a modified version of this program, you MUST
- Xinclude the source code.
- X
- XIf you modify this program, I would appreciate a copy of the new source
- Xcode. I am holding the copyright on the source code, so please don't
- Xdelete my name from the program files or from the documentation.
- X
- X
- XSUPPORT
- X=======
- X
- XI work very hard to produce a software package of the highest quality
- Xand functionality. I try to look into all reported bugs, and will
- Xgenerally fix reported problems within a few days.
- X
- XIN NO EVENT WILL I BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST
- XPROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES
- XARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR FOR ANY
- XCLAIM BY ANY OTHER PARTY.
- X
- XIf you have any questions, bugs, or suggestions, please contact me at:
- X
- X The Tool Shop BBS
- X (602) 279-2673 (FREE LINE, USR 2400)
- X (602) 264-3969 (HST 9600)
- X (602) 270-0239 (HAYES 9600)
- X
- XThe latest version is always available for downloading. (Except
- Xpossibly this portable version.)
- X
- XEnjoy! Samuel H. Smith
- X Author and Sysop of The Tool Shop.
- X
- SHAR_EOF
- if test 3086 -ne "`wc -c < 'unzip.doc'`"
- then
- echo shar: error transmitting "'unzip.doc'" '(should have been 3086 characters)'
- fi
- fi # end of overwriting check
- # End of shell archive
- exit 0
- --
- _ _ _ __
- ' ) ) ) / /) / ` / /) Michael Enkelis
- / / / o _. /_ __. _ // /-- __ /_ _ // o _ tektronix!vice!michaele
- / ' (_(_(__/ /_(_(_(<_(/_ (___, /) )_/ <_(<_(/_(_/_)_ (503) 627-4099
-
-